/*
 * Copyright (C) 2013 Daniel Treffenstädt <daniel@treffenstaedt.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "OString.h"

O_START_NAMESPACE
String::String(const String& s) :
	Object(),
	m_last(1)
{
	m_str	= s.m_str;
}

String::String(const char *s) :
	Object(),
	m_last(1)
{
	m_str	= s;
}

String::String(Char c) :
	Object(),
	m_last(1)
{
	m_str	= "";
	m_str.push_back(c);
}

String::String(std::string s) :
	Object(),
	m_last(1)
{
	m_str	= s;
}

String::String() :
	Object(),
	m_last(1)
{
	m_str	= "";
}

String String::arg(String s)
{
	replace(String("%") + m_last, s);
	m_last++;
	return *this;
}

String String::append(String s)
{
	m_str.append(s.m_str.c_str());
	return *this;
}

String String::append(Char c)
{
	m_str.push_back(c);
	return *this;
}

bool String::contains(String s)
{
	int len	= s.length();
	for (unsigned int i = 0; i < m_str.length(); i++)
	{
		if (substring(i, len) == s)
		{
			return true;
		}
	}
	return false;
}

bool String::contains(Char c)
{
	for (unsigned int i = 0; i < m_str.length(); i++)
	{
		if (charAt(i) == c)
		{
			return true;
		}
	}
	return false;
}

int String::occurs(String s)
{
	int res	= 0;
	int len	= s.length();
	for (unsigned int i = 0; i < m_str.length(); i++)
	{
		if (substring(i, len) == s)
		{
			res++;
		}
	}
	return res;
}

int String::occurs(Char c)
{
	int res	= 0;
	for (unsigned int i = 0; i < m_str.length(); i++)
	{
		if (charAt(i) == c)
		{
			res++;
		}
	}
	return res;
}

int String::pos(String s, bool left2right)
{
	int len	= s.length();
	if (left2right)
	{
		for (unsigned int i = 0; i < m_str.length(); i++)
		{
			if (substring(i, len) == s)
			{
				return i;
			}
		}
	}
	else
	{
		for (int i = m_str.length() - 1; i >= 0; i--)
		{
			if (substring(i - len, len) == s)
			{
				return i;
			}
		}
	}
	return -1;
}

String String::substring(int start, int length)
{
	if (start < 0)
	{
		start	+= m_str.length() - 1;
	}
	if (length == 0)
	{
		return String();
	}
	else if (length < 0)
	{
		length	= length * -1;
		start	-= length;
	}

	if (start + length > this->length())
	{
		return String();
	}

	return String(m_str.substr(start, length));
}

String String::remove(String s)
{
	if (!contains(s))
	{
		return *this;
	}

	String d(m_str);

	clear();

	int act	= 0;
	int len		= s.length();
	for (int i = 0; i < d.length(); i++)
	{
		if (act == 0)
		{
			append(d[i]);
		}
		else
		{
			act--;
		}
		if (d.substring(i, len) == s)
		{
			act	= len;
		}
	}

	return *this;
}

String String::remove(Char c)
{
	if (!contains(c))
	{
		return *this;
	}

	String d(m_str);

	clear();

	for (int i = 0; i < d.length(); i++)
	{
		if (d[i] != c)
		{
			append(d[i]);
		}
	}

	return *this;
}

String String::remove(int start, int length)
{
	if (start < 0)
	{
		start	+= m_str.length() - 1;
	}
	if (length == 0)
	{
		return *this;
	}
	else if (length < 0)
	{
		length	= length * -1;
		start	-= length;
	}

	if (start + length > this->length())
	{
		return *this;
	}

	String d(m_str);

	clear();

	for (int i = 0; i < d.length(); i++)
	{
		if (i < start || i >= start + length)
		{
			append(d[i]);
		}
	}

	return *this;
}

String String::replace(String find, String replace)
{
	if (!contains(find))
	{
		return *this;
	}


	String d(m_str);

	clear();

	int act	= 0;
	int len		= find.length();
	for (int i = 0; i < d.length(); i++)
	{
		if (act == 0)
		{
			append(d[i]);
		}
		else
		{
			if (act == len)
			{
				append(replace);
			}
			act--;
		}
		if (d.substring(i, len) == find)
		{
			act	= len;
		}
	}

	return *this;
}

String String::replace(Char find, Char replace)
{
	if (!contains(find))
	{
		return *this;
	}

	String d(m_str);

	clear();

	for (int i = 0; i < d.length(); i++)
	{
		if (d[i] == find)
		{
			append(replace);
		}
		else
		{
			append(d[i]);
		}
	}

	return *this;
}

void String::clear()
{
	m_str.clear();
}

int String::length()
{
	return m_str.length();
}

const char* String::c_str()
{
	return m_str.c_str();
}

Char String::operator [](int index)
{
	return (char) m_str.at(index);
}

Char String::charAt(int index)
{
	return (char) m_str.at(index);
}

int String::toInt()
{
	int res	= 0;
	bool in	= false;
	bool neg	= false;
	for (int i = 0; i < length(); i++)
	{
		Char c	= charAt(i);
		if (in)
		{
			if (c.isLetter())
			{
					res	*= 10;
					res	+= c.digit();
			}
			else
			{
				if (neg && res > 0)
				{
					res	*= -1;
				}
				return res;
			}
		}
		else if (c == '-' || c.isDigit())
		{
			in	= true;
			if (c == '-')
			{
				neg	= true;
			}
			else
			{
				res	= c.digit();
			}
		}
	}
	if (neg && res > 0)
	{
		res	*= -1;
	}
	return res;
}

double String::toDouble()
{
	int res		= 0;
	int after	= 0;
	bool comma	= false;
	bool in		= false;
	bool neg	= false;
	for (int i = 0; i < length(); i++)
	{
		Char c	= charAt(i);
		if (in)
		{
			if (c.isDigit())
			{
				res	*= 10;
				res	+= c.digit();
			}
			else if (c == '.')
			{
				comma	= true;
				break;
			}
			else
			{
				break;
			}
		}
		else if (comma)
		{
			if (c.isDigit())
			{
				after	*= 10;
				after	+= c.digit();
			}
			else
			{
				break;
			}
		}
		else if (c == '-' || c.isDigit())
		{
			in	= true;
			if (c == '-')
			{
				neg	= true;
			}
			else
			{
				res	= c.digit();
			}
		}
	}

	double af	= (double)after;
	while (af >= 1)
	{
		af	/= 10;
	}

	if (neg)
	{
		res	*= -1;
		return ((double) res) - af;
	}
	else
	{
		return ((double) res) + af;
	}
}

void String::print()
{
	std::cout<<m_str;
}

String String::read()
{
	String res;
	std::cin>>res.m_str;
	return res;
}

String String::number(short n)
{
	String res;
	if (n < 0)
	{
		res	= "-";
		n	*= -1;
	}
	else if (n == 0)
	{
		return String("0");
	}
	int fac = 10;
	while (fac < n)
	{
		fac *= 10;
	}
	fac /= 10;

	int f   = 0;
	int d   = 0;
	while (fac >= 1)
	{
		d		= (n - f) / fac;
		f		+= d * fac;
		fac		/= 10;
		res.append((char) (d+48));
	}

	return res;
}
String String::number(int n)
{
	String res;
	if (n < 0)
	{
		res	= "-";
		n	*= -1;
	}
	else if (n == 0)
	{
		return String("0");
	}
	int fac = 10;
	while (fac < n)
	{
		fac *= 10;
	}
	fac /= 10;

	int f   = 0;
	int d   = 0;
	while (fac >= 1)
	{
		d		= (n - f) / fac;
		f		+= d * fac;
		fac		/= 10;
		res.append((char) (d+48));
	}

	return res;
}
String String::number(long n)
{
	String res;
	if (n < 0)
	{
		res	= "-";
		n	*= -1;
	}
	else if (n == 0)
	{
		return String("0");
	}
	int fac = 10;
	while (fac < n)
	{
		fac *= 10;
	}
	fac /= 10;

	int f   = 0;
	int d   = 0;
	while (fac >= 1)
	{
		d		= (n - f) / fac;
		f		+= d * fac;
		fac		/= 10;
		res.append((char) (d+48));
	}

	return res;
}

bool String::equals(String s)
{
	return (*this) == s;
}

String String::operator +(String s)
{
	return String(m_str).append(s);
}

String String::operator +(Char c)
{
	return String(m_str).append(c);
}

void String::operator +=(String s)
{
	append(s);
}

void String::operator +=(Char c)
{
	append(c);
}

void String::operator= (String s)
{
	m_str	= s.m_str;
}

void String::operator =(const char* c)
{
	m_str	= c;
}

bool String::operator ==(String s)
{
	if (length() != s.length())
	{
		return false;
	}

	for (int i = 0; i < length(); i++)
	{
		if (charAt(i) != s[i])
		{
			return false;
		}
	}
	return true;
}

std::ostream& operator<<(std::ostream& s, String d)
{
	s<<d.m_str;
	return s;
}

std::istream& operator>>(std::istream& s, String& d)
{
	s>>d.m_str;
	return s;
}

String operator+ (const char* c, String s)
{
	return String(c).append(s);
}

String operator+ (std::string c, String s)
{
	return String(c).append(s);
}

O_END_NAMESPACE
